package com.imooc.settlement.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.settlement.dao.SettlementDao;
import com.imooc.settlement.dto.OrderMessageDTO;
import com.imooc.settlement.enummeration.OrderStatus;
import com.imooc.settlement.enummeration.SettlementStatus;
import com.imooc.settlement.po.SettlementPo;
import com.rabbitmq.client.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * ProjectName deliveryman
 *
 * @author xieyucan
 * <br>CreateDate 2022/9/20 17:33
 */
@Slf4j
@Service
public class OrderMessageService {

    @Autowired
    private SettlementDao settlementDao;

    @Autowired
    private SettlementService settlementService;

    ObjectMapper objectMapper=new ObjectMapper();

    DeliverCallback deliverCallback=((consumerTag, message) -> {
        String messageBody=new String(message.getBody());
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("43.138.244.235");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("1234");
        connectionFactory.setUsername("admin");

        try {
            OrderMessageDTO orderMessageDTO = objectMapper.readValue(messageBody, OrderMessageDTO.class);
            /*-----------------------------------------*/
            SettlementPo settlementPo=new SettlementPo();
            settlementPo.setAmount(orderMessageDTO.getPrice());
            settlementPo.setOrderId(orderMessageDTO.getOrderId());
            Integer transactionId = settlementService.settlement(orderMessageDTO.getAccountId(), orderMessageDTO.getPrice());
            settlementPo.setStatus(SettlementStatus.SUCCESS);
            settlementPo.setTransactionId(transactionId);
            settlementPo.setDate(new Date());
            settlementDao.insert(settlementPo);
            orderMessageDTO.setSettlementId(settlementPo.getId());
            /*-----------------------------------------*/

            try(Connection connection=connectionFactory.newConnection();
                Channel channel=connection.createChannel()){
                String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
                channel.basicPublish(
                        "exchange.settlement.order",
                        "key.order",
                        null,
                        messageToSend.getBytes()
                );
            }
        }catch (JsonProcessingException | TimeoutException e) {
            log.error(e.getMessage(),e);
        }
    });

    @Async
    public void handleMessage() throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("43.138.244.235");
        connectionFactory.setPort(5672);
        connectionFactory.setPassword("1234");
        connectionFactory.setUsername("admin");

        try (Connection connection=connectionFactory.newConnection();
             Channel channel=connection.createChannel()){
            channel.exchangeDeclare(
                    "exchange.order.settlement",
                    BuiltinExchangeType.FANOUT,
                    true,
                    false,
                    null);

            channel.queueDeclare(
                    "queue.settlement",
                    true,
                    false,
                    false,
                    null
            );
            channel.queueBind(
                    "queue.settlement",
                    "exchange.order.settlement",
                    "key.settlement"
            );
            channel.basicConsume(
                    "queue.settlement",
                    true,
                    deliverCallback,
                    consumerTag -> {}
            );
            while (true){
                Thread.sleep(10000000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
